﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;

using Qiang.Topology.Geometries;
using Qiang.Data;
using Qiang.Styles;

using Point = System.Drawing.Point;

namespace Qiang.Controls
{
    [Serializable]
    public class MapFunctionSelect : MapFunction
    {
        public MapFunctionSelect()
            : base()
        {
            MemoryStream stream = new MemoryStream(Images.cursorSelect);
            Cursor = new System.Windows.Forms.Cursor(stream);
            _selectPen = new Pen(Color.Black);
            _selectPen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
            this.layers = new List<IMapLayer>();
        }

        
        private List<IMapLayer> layers;

        #region 字段

        private bool _dragging = false;
        private Point _mousePosition;
        private Point _dragPoint;

        private bool _moveDragging = false;
        private Coordinate _moveDragPoint = null;
        private List<Coordinate> _moveRelatedPoints = new List<Coordinate>();

        Pen _selectPen;

        #endregion

        # region 方法

        public override void Active()
        {           
            base.Active();
            this.layers = this.MapControl.GetAllLayers();
        }

        public override void Deactive()
        {
            base.Deactive();

            foreach (IMapLayer layer in this.layers)
            {
                layer.ClearSelected();
            }

            this.layers = new List<IMapLayer>();

            this.MapControl.Refresh();
        }

        protected override void OnPaint(MapPaintArgs args)
        {
            base.OnPaint(args);

            if (this._moveDragging)
            {               
                foreach (Coordinate pt in this._moveRelatedPoints)
                {
                    args.MapGraphics.DrawLine(Pens.Red, this.MapControl.ProjToPixel(this._moveDragPoint), this.MapControl.ProjToPixel(pt));
                }
                args.MapGraphics.FillEllipse(Brushes.Red, new Rectangle(MapControl.ProjToPixel(this._moveDragPoint).X - 5, this.MapControl.ProjToPixel(this._moveDragPoint).Y-5, 10, 10));
            }

            if (this._dragging)
            {
                args.MapGraphics.DrawRectangle(_selectPen, new Rectangle(Math.Min(this._dragPoint.X, this._mousePosition.X), Math.Min(this._dragPoint.Y, this._mousePosition.Y),
                    Math.Abs(this._dragPoint.X - this._mousePosition.X) - 1, Math.Abs(this._dragPoint.Y - this._mousePosition.Y) - 1));
            }
        }


        protected override void OnMouseDown(MapMouseArgs e)
        {
            base.OnMouseDown(e);

            if (e.Button != System.Windows.Forms.MouseButtons.Left) return;

            Rectangle rect = new Rectangle(e.Location.X - 3, e.Location.Y - 3, 6, 6);
            Extent ext = this.MapControl.PixelToProj(rect);

            foreach (IMapLayer layer in this.layers)
            {
                if (layer is MapVectorLayer)
                {
                    bool b = (layer as MapVectorLayer).CheckPointForMove(ext, ref this._moveDragPoint, ref this._moveRelatedPoints);

                    if (b == true)
                    {
                        this._moveDragging = true;
                        return;
                    }
                }
            }

            MapControl.Map.ClearSelected();
            this._dragging = true;
            this._dragPoint = e.Location;
        }


        protected override void OnMouseMove(MapMouseArgs e)
        {
            base.OnMouseMove(e);

            int minx = Math.Min(Math.Min(this._dragPoint.X, this._mousePosition.X), e.Location.X);
            int miny = Math.Min(Math.Min(this._dragPoint.Y, this._mousePosition.Y), e.Location.Y);
            int maxx = Math.Max(Math.Max(this._dragPoint.X, this._mousePosition.X), e.Location.X);
            int maxy = Math.Max(Math.Max(this._dragPoint.Y, this._mousePosition.Y), e.Location.Y);

            this._mousePosition = e.Location;

            if (this._moveDragging)
            {
                this._moveDragPoint.X = e.GeoLocation.X;
                this._moveDragPoint.Y = e.GeoLocation.Y;
                MapControl.Invalidate();
            }
           
            if (this._dragging)
            {
                Rectangle rect = new Rectangle(minx, miny, maxx - minx, maxy - miny);
                rect.Inflate(10, 10);
                MapControl.Invalidate(rect);
            }

           
        }

        protected override void OnMouseUp(MapMouseArgs e)
        {
            base.OnMouseUp(e);

            if (this._moveDragging)
            {
                this._moveDragging = false;
                this._moveDragPoint = new Coordinate();
                this._moveRelatedPoints = new List<Coordinate>();
            }

            if (this._dragging)
            {
                this._dragging = false;

                Rectangle rect = new Rectangle(Math.Min(this._dragPoint.X, e.Location.X), Math.Min(this._dragPoint.Y, e.Location.Y),
                    Math.Abs(this._dragPoint.X - e.Location.X), Math.Abs(this._dragPoint.Y - e.Location.Y));

                Extent ext = this.MapControl.PixelToProj(rect);
                MapControl.Map.Select(ext, SelectionMode.Marquee);
            }

            this.MapControl.Refresh();
        }


        protected override void OnMouseClick(MapMouseArgs e)
        {
            if (_dragPoint != e.Location) return;
            if (_dragging) _dragging = false;
            if (_moveDragging) _moveDragging = false;

            Rectangle rect = new Rectangle(e.X - 2, e.Y - 2, 4, 4);
            Extent ext = MapControl.PixelToProj(rect);
            MapControl.Map.Select(ext, SelectionMode.Click);

            base.OnMouseClick(e);
        }

        protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
        {
            base.OnKeyDown(e);
        }


        protected override void OnKeyUp(System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode == System.Windows.Forms.Keys.Delete) MapControl.Map.RemoveSelected();
            if (e.KeyCode == System.Windows.Forms.Keys.Escape)
            {
                if (_dragging == true) 
                    _dragging = false;
                else if (_moveDragging) 
                    _moveDragging = false;
                else
                    MapControl.Map.ClearSelected();
            }
            base.OnKeyUp(e);
        }







        # endregion


    }
}
